﻿(*
	Pylint Syntax Checker for BBEdit
	Vaclav Spirhanzl

	see pylint_validator handler for necessary modifications

	Version: 1.0.0
	Date: 14. November 2011

	Thanks to:
		John Gruber - http://daringfireball.net/projects/csschecker/

	This AppleScript is released under a Creative Commons Attribution-ShareAlike License:
		<http://creativecommons.org/licenses/by-sa/2.0/>

*)-- Binary-coded decimal of applescript version 1.10property AS_VERSION_1_10 : 17826208on run	-- The run handler is called when the script is invoked normally,	-- such as from BBEdit's Scripts menu.	my check_lint()end runon menuselect()	-- The menuselect() handler gets called when the script is invoked	-- by BBEdit as a menu script. Save this script, or an alias to it,	-- as "Check•Pylint" in the "Menu Scripts" folder in your	-- "BBEdit Support" folder.	tell application "BBEdit"		try			if (source language of window 1 is "Python") then				my check_lint()				return true			else				my show_alert("Pylint - BBEdit", "")				return false			end if		end try	end tellend menuselecton check_lint()	local py_path, my_kind, pylint_error_list, pylint_report, pylint_report_b	set py_path to my get_file_path()	if py_path is "" then return -- Don't proceed if we don't have a path to the Python file		try		set check_result to my pylint_validator(py_path)	on error err_text number err_num		-- Cancel butto pressed		if (err_text as integer) is -128 then			return false		end if		if err_num ≠ 18 then -- Warning message - "No config file found, using default configuration"			my show_alert("Pylint - Check result error", (err_num as text) & ": " & err_text)			return false		end if	end try		set pylint_error_list to {}	set pylint_report to {}		tell application "BBEdit"		set current_file to file of text window 1		set document_name to name of document of text window 1				if check_result starts with "No syntax errors detected" then			my show_alert("Pylint Syntax OK", ¬				"No Pylint errors or warnings were found in “" & document_name & "”.")			return		end if				-- Put together the results for the browser:		set in_report to false		repeat with err in (every paragraph of check_result)			if (err as text) is not equal to "" then				try					if in_report then						copy (err as text) & return to end of pylint_report					end if					if (word 1 of err starts with "Report") then						copy (err as text) & return to end of pylint_report						set in_report to true					end if					if (word 1 of err) is "E" or (word 1 of err) is "F" then						set my_kind to error_kind					else if (word 1 of err) is "W" then						set my_kind to warning_kind					else if (word 1 of err) is "C" or (word 1 of err) is "R" then						set my_kind to note_kind					else						set my_kind to "Unknown"					end if				on error					set my_kind to "Unknown"				end try								if my_kind is not "Unknown" then					set old_delims to AppleScript's text item delimiters					set AppleScript's text item delimiters to ":"					set err_description to text item 3 of err					try						set err_description to err_description & ": " & text item 4 of err					end try					set line_num to word 2 of err as integer					set AppleScript's text item delimiters to old_delims										set err_list_item to {result_kind:¬						my_kind, result_file:¬						current_file, result_line:¬						line_num, message:err_description as text}					copy err_list_item to end of pylint_error_list				end if			end if		end repeat				if (pylint_report as text) starts with "Report" then			set pylint_report_b to {}			set pylint_report_b to my report_beauty(pylint_report)			make new text window with properties {contents:pylint_report_b as text, name:document_name & " - Pylint Report - Output"}		end if		make new results browser with data pylint_error_list with properties {name:document_name & " - PyLint Syntax Analysis - Output"}			end tellend check_linton get_file_path()	-- Input: None	-- Returns:	--	Path to the Python file to be passed to the validator. Returns an empty	--	string if an error occurs or if the frontmost window is an untitled	--	document. 		local pfile_path, act_docu	set pfile_path to "" -- file name with Python source code		tell application "BBEdit"		try			-- Make sure the frontmost window is a text window, and			-- that it is not an untitled (never saved) document and			-- contains Python code			if (class of window 1 is not project window) then error			set act_docu to active document of window 1			if not (on disk of act_docu) then error number 10000			if (source language of window 1 is not "Python") then error number 10001			if (modified of act_docu) then error number 10002						set pfile_path to (file of act_docu) as text			set pfile_path to POSIX path of pfile_path		on error number n			-- As of BBEdit 8.2.3, result browser entries must be associated			-- with a file on disk.			if (n = 10000) then				my show_warning("Pylint Check: untitled document error", ¬					"Pylint Check does not work with untitled documents. Save your document, then try again.")			else if (n = 10001) then				my show_warning("Pylint Check: Python document", ¬					"Active window does not containt a Python source code.")			else if (n = 10002) then				my show_warning("Pylint Check: Python document", ¬					"Document must be saved on disc before Pylint check.")			else				beep			end if			return "" -- Don't proceed with the rest of the script.		end try	end tell	return pfile_pathend get_file_pathon pylint_validator(py_path)	-- Input: Quoted form of posix path of python file	-- Returns: Output from Pylint:	-- you have to modify content of pylin_path and pylint_parm	-- according your configuration		set shell_result to ""		set pylint_path to "/usr/local/bin/pylint"	set pylint_parm to "--rcfile=" & "'/Users/Vasek/Library/Application Support/PyLint/pylint.rcfile'"	try		set dialogAnswer to display dialog ¬			"Do you want to generate PyLint detailed report" with title ¬			"Pylint Syntax Check" buttons {"Cancel", "No", "Yes"} cancel button ¬			"Cancel" default button "No" with icon note giving up after 30		if gave up of dialogAnswer then			error -128 -- same as a cancel button		end if		if button returned of dialogAnswer is "Yes" then			set pylint_parm to pylint_parm & space & "--reports=y"		else if button returned of dialogAnswer is "No" then			-- button returned is "No"			set pylint_parm to pylint_parm & space & "--reports=n"		end if	on error number n		error n	end try		set my_shell_cmd to pylint_path & space & quoted form of py_path as string	set my_shell_cmd to my_shell_cmd & space & pylint_parm as string	set my_shell_cmd to my_shell_cmd & " | cat" as string		try		set shell_result to do shell script my_shell_cmd -- without altering line endings	end try	if shell_result is "" then error	return shell_result	end pylint_validatoron report_beauty(report_list)		local beauty_report_list	set beauty_report_list to {}		repeat with report_line in report_list		if report_line starts with "Messages" then			copy (" " & return as text) to end of beauty_report_list			copy (" " & return as text) to end of beauty_report_list		end if		if report_line starts with "Global" then			copy (" " & return as text) to end of beauty_report_list			copy (" " & return as text) to end of beauty_report_list		end if		if report_line starts with "Statistics" then			copy (" " & return as text) to end of beauty_report_list			copy (" " & return as text) to end of beauty_report_list		end if		if report_line starts with "Raw m" then			copy (" " & return as text) to end of beauty_report_list			copy (" " & return as text) to end of beauty_report_list		end if		if report_line starts with "Duplication" then			copy (" " & return as text) to end of beauty_report_list			copy (" " & return as text) to end of beauty_report_list		end if		copy (report_line as text) to end of beauty_report_list	end repeat	return beauty_report_listend report_beautyon show_alert(the_title, the_message)	if ((system attribute "ascv") ≥ AS_VERSION_1_10) then		-- AppleScript 1.10 or later (10.4)		display alert the_title message the_message	else		display dialog the_title & return & return & the_message ¬			buttons {"OK"} default button 1 with icon note	end if	returnend show_alerton show_warning(the_title, the_message)	if ((system attribute "ascv") ≥ AS_VERSION_1_10) then		-- AppleScript 1.10 or later (10.4)		display alert the_title message the_message as warning	else		display dialog the_title & return & return & the_message ¬			buttons {"OK"} default button 1 with icon caution	end if	returnend show_warning